package com.fs.system.security;

import com.fs.common.constant.CacheConstants;
import com.fs.common.core.pojo.SysUser;
import com.fs.common.exception.user.UserPasswordNotMatchException;
import com.fs.common.exception.user.UserPasswordRetryLimitExceedException;
import com.fs.common.util.RedisCache;
import com.fs.common.util.sign.PasswordUtils;
import com.fs.system.config.SysPasswordProperties;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;

import java.util.concurrent.TimeUnit;

/**
 * @author suke
 * @version 1.0
 * @title MyDaoAuthenticationProvider
 * @description
 * @create 2024/7/26 9:39
 */
public class MyDaoAuthenticationProvider  extends DaoAuthenticationProvider {
    private RedisCache redisCache;
    private SysPasswordProperties passwordProperties;
    public MyDaoAuthenticationProvider(UserDetailsService userDetailsService,RedisCache redisCache, PasswordEncoder passwordEncoder, SysPasswordProperties passwordProperties) {
        this.redisCache = redisCache;
        this.setPasswordEncoder(passwordEncoder);
        this.passwordProperties = passwordProperties;
        this.setUserDetailsService(userDetailsService);
    }

    @Override
    protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
        if (authentication.getCredentials() == null) {
            this.logger.debug("Failed to authenticate since no credentials provided");
            throw new BadCredentialsException(this.messages
                    .getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
        }
        //用户输入密码
        String presentedPassword = authentication.getCredentials().toString();
        //获取用户名
        String username = authentication.getPrincipal().toString();
        Integer retryCount = redisCache.getCacheObject(getCacheKey(username));

        if (retryCount == null) {
            retryCount = 0;
        }

        if (retryCount >= Integer.valueOf(passwordProperties.getMaxRetryCount()).intValue()) {
            throw new UserPasswordRetryLimitExceedException(passwordProperties.getMaxRetryCount(), passwordProperties.getLockTime());
        }

        if (!this.getPasswordEncoder().matches(presentedPassword, userDetails.getPassword()))
        {
            retryCount = retryCount + 1;
            redisCache.setCacheObject(getCacheKey(username), retryCount, passwordProperties.getLockTime(), TimeUnit.MINUTES);
            throw new UserPasswordNotMatchException();
        }
        else{
            clearLoginRecordCache(username);
        }

    }


    /**
     * 登录账户密码错误次数缓存键名
     *
     * @param username 用户名
     * @return 缓存键key
     */
    private String getCacheKey(String username){
        return CacheConstants.PWD_ERR_CNT_KEY + username;
    }

    public void validate(SysUser user,String password) {

    }

    public void clearLoginRecordCache(String loginName){
        if (redisCache.hasKey(getCacheKey(loginName))){
            redisCache.deleteObject(getCacheKey(loginName));
        }
    }
}
